﻿#ifndef XJ_HASH_H
#define XJ_HASH_H

#include "list.h"

typedef void *(*PFN_LOCK_CREATE)(void *context);
typedef int  (*PFN_LOCK_LOCK)(void *lock, void *context);
typedef int  (*PFN_LOCK_UNLOCK)(void *lock, void *context);
typedef void (*PFN_LOCK_DESTROY)(void *lock, void *context);

/** @struct hash_lock_callback
 *  @brief hash锁操作回调函数
 */
struct hash_lock_callback
{
    void *context;
    PFN_LOCK_CREATE create;
    PFN_LOCK_LOCK lock;
    PFN_LOCK_UNLOCK unlock;
    PFN_LOCK_DESTROY destroy;
};

/** @struct hash
 *  @brief hash数据结构
 */
struct hash
{
    struct hlist_head *bucket;                      ///< 桶数组
    void **bucket_lock;                             ///< 桶链表锁
    unsigned int bucket_count;                      ///< 桶数组大小
    struct hash_lock_callback lock_callback;        ///< 锁操作回调函数
};

/** @typedef unsigned int (*PFN_HASH_CHOOSE)(const void *data, unsigned int bucket_count)
 *  @brief 通过data计算hash值的回调
 */
typedef unsigned int (*PFN_HASH_CHOOSE)(const void *data, unsigned int bucket_count);


/** @typedef int (*PFN_HASH_COMPARE)(const struct hlist_node *node, const void *data)
 *  @brief 比较hash内的data_node与data代表的hash是否相同的回调函数
 */
typedef int (*PFN_HASH_COMPARE)(const struct hlist_node *node, const void *data);


/** @typedef void (*PFN_HASH_VISITOR)(struct hlist_node *node, const void *arg)
 *  @brief 遍历hash每个node的回调函数
 */
typedef void (*PFN_HASH_VISITOR)(struct hlist_node *node, const void *arg);


/** 
 *  @fn struct hash *hash_create(unsigned int bucket_count, const struct hash_lock_callback *lock_callback)
 *  @brief 创建一个hash实例
 *  @param bucket_count 桶的数量
 *  @param lock_callback 锁操作回调函数
 *  @return hash实例
 */
struct hash *hash_create(unsigned int bucket_count, const struct hash_lock_callback *lock_callback);


/** 
 *  @fn int hash_add(struct hash *h, PFN_HASH_COMPARE compare, PFN_HASH_CHOOSE choose, const void *data, struct hlist_node *data_node)
 *  @brief 添加一个data_node到hash中
 *  @param instance hash实例
 *  @param compare 用于比较已有data_node与新增的data是否相同的回调函数, 返回非0表示存在相同的数据, 将不执行添加
 *  @param choose 用于从data计算出hash值(桶的位置)的回调函数
 *  @param data 用于计算hash值和比较的数据
 *  @param data_node 新增的数据的节点
 *  @retval 0 data_node添加成功
 *  @retval -1 compare返回非0, data_node未添加到(或已存于)hash
 */
int hash_add(struct hash *instance, PFN_HASH_COMPARE compare, PFN_HASH_CHOOSE choose, const void *data, struct hlist_node *data_node);


/** 
 *  @fn struct hlist_node *hash_remove(struct hash *instance, PFN_HASH_COMPARE compare, PFN_HASH_CHOOSE choose, void *data)
 *  @brief 移除一个data_node
 *  @param instance hash实例
 *  @param compare 用于比较已有data_node与新增的data是否相同的回调函数
 *  @param choose 用于从data计算出hash值(桶的位置)的回调函数
 *  @param data 用于计算hash值和比较的数据
 *  @return 被移除的data_node
 *  @retval NULL 没有找到该项
 */
struct hlist_node *hash_remove(struct hash *instance, PFN_HASH_COMPARE compare, PFN_HASH_CHOOSE choose, void *data);



/** 
 *  @fn void hash_for_each(struct hash *instance, PFN_HASH_VISITOR callback, void *arg)
 *  @brief 遍历一个hash
 *  @param instance hash实例
 *  @param callback 对每个data_node进行处理的回调
 *  @param arg 用于callback的额外参数
 *  @return
 */
void hash_for_each(struct hash *instance, PFN_HASH_VISITOR callback, void *arg);



/** 
 *  @fn struct hlist_node *hash_find(struct hash *instance, PFN_HASH_COMPARE callback, void *data)
 *  @brief 在hash中查找node
 *  @param instance hash实例
 *  @param choose 用于计算data的hash的回调
 *  @param compare 比较是否match的回调
 *  @param data 用于callback的参数
 *  @return 找到的节点或NULL
 */
struct hlist_node *hash_find_ex(struct hash *instance, PFN_HASH_CHOOSE choose, PFN_HASH_COMPARE compare, void *data);


/** 
 *  @fn struct hlist_node *hash_find(struct hash *instance, PFN_HASH_COMPARE callback, void *data)
 *  @brief 在hash中查找node
 *  @param instance hash实例
 *  @param compare 比较是否match的回调
 *  @param data 用于callback的参数
 *  @return 找到的节点或NULL
 *  @note 在无法计算bucketid的时候将会遍历整个hash, 性能比ex版本低
 */
struct hlist_node *hash_find(struct hash *instance, PFN_HASH_COMPARE compare, void *data);


/** 
 *  @fn void hash_destroy(struct hash *instance, PFN_HASH_FREE free_cb, void *arg)
 *  @brief 释放一个hash实例
 *  @param instance hash实例
 *  @param free_callback 用于释放hash实例内剩余数据的回调函数, 可以为NULL
 *  @param arg 用于free_callback的额外参数
 *  @return
 */
void hash_destroy(struct hash *instance, PFN_HASH_VISITOR free_callback, void *arg);


#endif // XJ_HASH_H
